using System;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Collections;
using System.Xml;
using System.Collections.Generic;
using System.Runtime.Serialization;


using Infragistics.Win.Misc;
using Infragistics.Win.Misc.UltraWinNavigationBar;


using FinancialAnalyzer.MoneyFlow;
using FinancialAnalyzer.ToolClasses;
using FinancialAnalyzer.DataBase;


using GemBox.Spreadsheet;

namespace FinancialAnalyzer
{

    public partial class MainForm : Form
    {   
        /*
        //http://www.simple-talk.com/dotnet/.net-framework/implementing-real-world-data-input-validation-using-regular-expressions/
        //http://www.codeproject.com/KB/dotnet/System_File_Association.aspx
        //http://www.dotnetspider.com/resources/5387-how-cam-we-delete-datagridview-rows.aspx
        //http://www.codeproject.com/KB/grid/multicolumn_sort.aspx
         */

        #region Variablen

        private readonly String SERIALIZED_FILE_NAME = "ListSerDb.ogo";
        private readonly Char[] splitChar = { '\\' };
        private readonly Regex DigitRegex = new Regex(@"^-?[0-9]+(\,[0-9]+)?$");
        private readonly Regex WhiteSpaceRegex = new Regex(@"^\s+$");
        private readonly Regex YearRegex = new Regex("\\d{4}");
        private readonly int _historyCount = 16;
        private readonly String TABLE_NAME_LEFT = "Income";
        private readonly String TABLE_NAME_RIGHT = "Outcome";

        private DataGridView.HitTestInfo hitTestInfoIn;
        private DataGridView.HitTestInfo hitTestInfoOut;

        private MoneyFlowTreeHandler _moneyFlowDB;
        private BindingSource _datenBinderIncome;
        private BindingSource _datenBinderOutcome;
        private MFMForm MFSetup;


        private Stack<Pfad> _historyInBackStack;
        private Stack<Pfad> _historyInForwardStack;
        private Stack<Pfad> _historyOutBackStack;
        private Stack<Pfad> _historyOutForwardStack;
        #endregion


        private ImageList _treeviewImageList;

        
        public MainForm()
        {
            #region Init Main
            InitializeComponent();

            _moneyFlowDB = new MoneyFlowTreeHandler(SERIALIZED_FILE_NAME, TABLE_NAME_LEFT, TABLE_NAME_RIGHT);         


            if (_moneyFlowDB.ItemList.Count > 0)
            {
                MFSetup = new MFMForm(_moneyFlowDB.ItemList);
                MFSetup.Owner = this;
                MFSetup.TopMost = true;
                MFSetup.StartPosition = FormStartPosition.CenterParent;
            }
            else
            {
                MFSetup = new MFMForm();
                MFSetup.Owner = this;
                MFSetup.TopMost = true;
                MFSetup.StartPosition = FormStartPosition.CenterParent;
                switch (MFSetup.ShowDialog())
                {
                    case DialogResult.Cancel:
                        break;
                    case DialogResult.OK:
                        _moneyFlowDB.initController(MFSetup.ItemList, false);
                        break;
                    default:
                        break;
                }
            }


            #region Init Eingabekomponenten
            _historyInBackStack = new Stack<Pfad>(_historyCount);
            _historyInForwardStack = new Stack<Pfad>(_historyCount);
            _historyInBackStack.Push(new Pfad("Income"));


            _historyOutBackStack = new Stack<Pfad>(_historyCount);
            _historyOutForwardStack = new Stack<Pfad>(_historyCount);
            _historyOutBackStack.Push(new Pfad("Outcome"));


            panelInAdd.Enabled = false;
            panelOutAdd.Enabled = false;


            domainUpDownOutMonth.SelectedIndex = _moneyFlowDB.CurrentMonth - 1;
            domainUpDownInMonth.SelectedIndex = _moneyFlowDB.CurrentMonth - 1;


            numericUpDownOutYear.Value = _moneyFlowDB.CurrentYear;
            numericUpDownInYear.Value = _moneyFlowDB.CurrentYear;


            _treeviewImageList = new ImageList();
            _treeviewImageList.Images.Add(Image.FromFile(@"E:\Documents\Visual Studio 2005\Projects\FinancialAnalyzer\FinancialAnalyzer\Images\Folder-small.png"));
            _treeviewImageList.Images.Add(Image.FromFile(@"E:\Documents\Visual Studio 2005\Projects\FinancialAnalyzer\FinancialAnalyzer\Images\Folder-close-small.png"));


            //treeViewIncome.ImageList = _treeviewImageList;
            //treeViewIncome.ShowPlusMinus = false;
            //treeViewIncome.ShowLines = false;
            treeViewIncome.LineColor = Color.DarkGreen;


            #endregion


            #endregion
            
            #region Init Income
            _datenBinderIncome = new BindingSource();


            _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income];
            dataGridViewIncome.DataSource = _datenBinderIncome;
            if (dataGridViewIncome.Columns.Count > 0)
            {
                dataGridViewIncome.Columns[0].HeaderText = "Collection";
                dataGridViewIncome.Columns[1].HeaderText = "Total";
            }    
            
            dataGridViewIncome.ReadOnly = true;
            #endregion

            #region Init Outcome
            _datenBinderOutcome = new BindingSource();


            _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome];
            dataGridViewOutcome.DataSource = _datenBinderOutcome;
            if (dataGridViewOutcome.Columns.Count > 0)
            {
                dataGridViewOutcome.Columns[0].HeaderText = "Collection";
                dataGridViewOutcome.Columns[1].HeaderText = "Total";  
            }            
            dataGridViewOutcome.ReadOnly = true;
            #endregion


            StatisticForm stats = new StatisticForm(_moneyFlowDB[EFlowDirection.Income, "work", "2009"]);
            //stats.Show();
        }

        #region Misc

        private void setUpMainForm()
        {
            BuildTreeIncome();
            BuildTreeOutcome();


            listBoxIn.Items.Clear();
            listBoxOut.Items.Clear();
            foreach (MoneyFlowItem item in _moneyFlowDB.ItemList)
            {
                switch (item.FlowDirection)
                {
                    case EFlowDirection.Income:
                        listBoxIn.Items.Add(item.Name);
                        break;
                    case EFlowDirection.Outcome:
                        listBoxOut.Items.Add(item.Name);
                        break;
                    default:
                        break;
                }
            }
        }

        private void setupColorOfDataGrdiView(DataGridView datagrid)
        {
            int hValue = 93;
            int sValue = 200;
            int lValue = 123;

            List<KeyValuePaar<int, Double>> valueList = new List<KeyValuePaar<int, double>>();

            for (int i = 0; i < datagrid.Rows.Count; i++)
            {
                valueList.Add(new KeyValuePaar<int, double>(i, (Double)datagrid.Rows[i].Cells[1].Value));
            }

            Boolean sortiert = true;
            for (int i = 0; i < valueList.Count && sortiert; i++)
            {
                sortiert = false;
                for (int j = 0; j < valueList.Count - 1 - i; j++)
                {
                    if (valueList[j].Value < valueList[j + 1].Value)
                    {
                        sortiert = true;
                        KeyValuePaar<int, double> temp = valueList[j];
                        valueList[j] = valueList[j + 1];
                        valueList[j + 1] = temp;
                    }
                }
            }

            for (int i = valueList.Count - 1; i >= 0; i--)
            {
                datagrid.Rows[i].DefaultCellStyle.BackColor = HslToRgb(hValue, sValue, lValue);
                hValue -= 15;
                hValue= hValue > 1 ? hValue : hValue<0 ? 0 : hValue;
            }
        }
        //This method converts the values to RGB
        public Color HslToRgb(double Hue, double Saturation, double Lightness)
        {
            double num4 = 0.0;
            double num5 = 0.0;
            double num6 = 0.0;
            double num = ((double)Hue) % 360.0;
            double num2 = ((double)Saturation) / 100.0;
            double num3 = ((double)Lightness) / 100.0;
            if (num2 == 0.0)
            {
                num4 = num3;
                num5 = num3;
                num6 = num3;
            }
            else
            {
                double d = num / 60.0;
                int num11 = (int)Math.Floor(d);
                double num10 = d - num11;
                double num7 = num3 * (1.0 - num2);
                double num8 = num3 * (1.0 - (num2 * num10));
                double num9 = num3 * (1.0 - (num2 * (1.0 - num10)));
                switch (num11)
                {
                    case 0:
                        num4 = num3;
                        num5 = num9;
                        num6 = num7;
                        break;
                    case 1:
                        num4 = num8;
                        num5 = num3;
                        num6 = num7;
                        break;
                    case 2:
                        num4 = num7;
                        num5 = num3;
                        num6 = num9;
                        break;
                    case 3:
                        num4 = num7;
                        num5 = num8;
                        num6 = num3;
                        break;
                    case 4:
                        num4 = num9;
                        num5 = num7;
                        num6 = num3;
                        break;
                    case 5:
                        num4 = num3;
                        num5 = num7;
                        num6 = num8;
                        break;
                }
            }
            //return new RgbColor((int)(num4 * 255.0), (int)(num5 * 255.0), (int)(num6 * 255.0));
            return Color.FromArgb((int)(r * 255.0f), (int)(g * 255.0f), (int)(b * 255.0f));
        }
        //The structure that will hold the RGB Values
        public struct RgbColor
        {
            public RgbColor(int r, int g, int b)
            {
                red = r;
                green = g;
                blue = b;
            }
            public int red;
            public int green;
            public int blue;
        }

        public static Color HSL2RGB(double h, double sl, double l)
        {

            double v;

            double r, g, b;



            r = l;   // default to gray

            g = l;

            b = l;

            v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);

            if (v > 0)
            {

                double m;

                double sv;

                int sextant;

                double fract, vsf, mid1, mid2;



                m = l + l - v;

                sv = (v - m) / v;

                h *= 6.0;

                sextant = (int)h;

                fract = h - sextant;

                vsf = v * sv * fract;

                mid1 = m + vsf;

                mid2 = v - vsf;

                switch (sextant)
                {

                    case 0:

                        r = v;

                        g = mid1;

                        b = m;

                        break;

                    case 1:

                        r = mid2;

                        g = v;

                        b = m;

                        break;

                    case 2:

                        r = m;

                        g = v;

                        b = mid1;

                        break;

                    case 3:

                        r = m;

                        g = mid2;

                        b = v;

                        break;

                    case 4:

                        r = mid1;

                        g = m;

                        b = v;

                        break;

                    case 5:

                        r = v;

                        g = m;

                        b = mid2;

                        break;

                }

            }

            //return Color.FromArgb((int)(r * 255.0f), (int)(g * 255.0f), (int)(b * 255.0f));
            return Color.FromArgb((int)Math.Abs(r % 255), (int)Math.Abs(g % 255), (int)Math.Abs(b % 255));
        }
        public static Color HSLtoRGB(Double H, Double S, Double L)
        {
            double r = 0, g = 0, b = 0;
            double temp1, temp2;

            if (L == 0)
            {
                r = g = b = 0;
            }
            else
            {
                if (S == 0)
                {
                    r = g = b = L;
                }
                else
                {
                    temp2 = ((L <= 0.5) ? L * (1.0 + S) : L + S - (L * S));
                    temp1 = 2.0 * L - temp2;

                    double[] t3 = new double[] { H + 1.0 / 3.0, H, H - 1.0 / 3.0 };
                    double[] clr = new double[] { 0, 0, 0 };

                    for (int i = 0; i < 3; i++)
                    {
                        if (t3[i] < 0)
                            t3[i] += 1.0;
                        if (t3[i] > 1)
                            t3[i] -= 1.0;

                        if (6.0 * t3[i] < 1.0)
                            clr[i] = temp1 + (temp2 - temp1) * t3[i] * 6.0;

                        else if (2.0 * t3[i] < 1.0)
                            clr[i] = temp2;

                        else if (3.0 * t3[i] < 2.0)
                            clr[i] = (temp1 + (temp2 - temp1) * ((2.0 / 3.0) - t3[i]) * 6.0);

                        else
                            clr[i] = temp1;
                    }

                    r = clr[0];
                    g = clr[1];
                    b = clr[2];
                }
            }

            return Color.FromArgb((int)Math.Abs(r % 255), (int)Math.Abs(g % 255), (int)Math.Abs(b % 255));
        }

        private bool MonthInEnum(String month)
        {
            Boolean included = false;
            foreach (object item in Enum.GetValues(typeof(EMonth)))
            {
                included = month.Equals(item.ToString());
                if (included)
                {
                    break;
                }
            }
            return included;
        }

        private void setUpColumnText(DataGridView datagrid, int level)
        {
            switch (level)
            {
                case 1:
                    datagrid.Columns[0].HeaderText = "Collection";
                    datagrid.Columns[1].HeaderText = "Total";
                    break;
                case 2:
                    datagrid.Columns[0].HeaderText = "Year";
                    datagrid.Columns[1].HeaderText = "Total";
                    break;
                case 3:
                    datagrid.Columns[0].HeaderText = "Month";
                    datagrid.Columns[1].HeaderText = "Total";
                    break;
                case 4:
                    datagrid.Columns[0].HeaderText = "Comment";
                    datagrid.Columns[1].HeaderText = "Value";
                    break;
                default:
                    break;
            }
        }
        
        #endregion

        #region EventHandler Income

        #region Misc

        private void setUpIncomeAddComponents()
        {
            String[] path = treeViewIncome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
            listBoxIn.SelectedIndex = listBoxIn.Items.IndexOf(path[1]);
            numericUpDownInYear.Value = Decimal.Parse(path[2]);
            domainUpDownInMonth.Text = path[3];
        }

        #endregion

        #region ContextMenu
        private void deleteToolStripMenuItemIncome_Click(object sender, EventArgs e)
        {
            String[] path = treeViewIncome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
            if (!dataGridViewIncome.Rows[hitTestInfoIn.RowIndex].IsNewRow && path.Length > 3)
            {
                DialogResult response = MessageBox.Show("Are you sure want to delete the row?", dataGridViewIncome.Rows[hitTestInfoIn.RowIndex].Cells[0].Value.ToString(), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                if (response == DialogResult.Yes)
                {
                    dataGridViewIncome.Rows.RemoveAt(hitTestInfoIn.RowIndex);
                    _moneyFlowDB.Delete(EFlowDirection.Income, path[1], path[2], path[3], hitTestInfoIn.RowIndex);
                    _moneyFlowDB.Sum(EFlowDirection.Income);
                }
            }
        }

        private void refreshToolStripMenuItemIncome_Click(object sender, EventArgs e)
        {
            _moneyFlowDB.Sum(EFlowDirection.Income);
        }

        private void dataGridViewIncome_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                hitTestInfoIn = dataGridViewIncome.HitTest(e.X, e.Y);
                if (hitTestInfoIn.RowIndex >= 0 && hitTestInfoIn.ColumnIndex > 0)
                {
                    if (!dataGridViewIncome.Rows[hitTestInfoIn.RowIndex].IsNewRow)
                    {
                        if (hitTestInfoIn.Type == DataGridViewHitTestType.Cell && hitTestInfoIn.RowIndex == hitTestInfoIn.RowIndex)
                        {
                            contextMenuStripIn.Show(dataGridViewIncome, new Point(e.X, e.Y));
                        }
                        dataGridViewIncome.Rows[hitTestInfoIn.RowIndex].Selected = true;
                        dataGridViewIncome.CurrentCell = dataGridViewIncome[hitTestInfoIn.ColumnIndex, hitTestInfoIn.RowIndex];
                    }
                }
            }
        }
        #endregion

        #region TreeNode
        private void selectNodeinTree(string key, EFlowDirection inout)
        {
            switch (inout)
            {
                case EFlowDirection.Income:
                    TreeNode[] nodesIn = treeViewIncome.Nodes.Find(key, true);
                    if (nodesIn.GetLength(0) > 0)
                    {
                        treeViewIncome.SelectedNode = nodesIn[0];
                    }
                    else
                    {
                        throw new Exception("Node: " + key + " not found!");
                    }
                    break;
                case EFlowDirection.Outcome:
                    TreeNode[] nodesOut = treeViewOutcome.Nodes.Find(key, true);
                    if (nodesOut.GetLength(0) > 0)
                    {
                        treeViewOutcome.SelectedNode = nodesOut[0];
                    }
                    else
                    {
                        throw new Exception("Node: " + key + " not found!");
                    }
                    break;
            }


        }

        private void BuildTreeIncome()
        {
            treeViewIncome.Nodes[0].Nodes.Clear();
            //Income - Treeview
            foreach (KeyValuePaar<IMoneyFlowItem, Double> classReference in _moneyFlowDB[EFlowDirection.Income])
            {
                treeViewIncome.BeginUpdate();
                String name = classReference.Key.Classname;
                treeViewIncome.Nodes[0].Nodes.Add(name, name, 1);


                foreach (KeyValuePaar<Year, Double> year in _moneyFlowDB[EFlowDirection.Income, name])
                {
                    treeViewIncome.Nodes[0].Nodes[name].Nodes.Add(name + "-" + year.Key.ToString(), year.Key.ToString(), 0);
                    foreach (KeyValuePaar<Month, Double> month in _moneyFlowDB[EFlowDirection.Income, name, year.Key.ToString()])
                    {
                        treeViewIncome.Nodes[0].Nodes[name].Nodes[name + "-" + year.Key.ToString()].Nodes.Add(name + "-" + year.Key.ToString() + "-" + month.Key.ToString(), month.Key.ToString(), 1);
                    }
                }
                treeViewIncome.EndUpdate();
            }
        }

        private void treeViewIncome_AfterSelect(object sender, TreeViewEventArgs e)
        {
            dataGridViewIncome.ReadOnly = true;
            panelInAdd.Enabled = false;
            _historyInBackStack.Push(new Pfad(e.Node.FullPath));


            switch (e.Node.Level)
            {
                //Show all Income clases in the List
                case 0:
                    _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income];
                    break;
                //Show all Years in a Income class
                case 1:
                    _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income, e.Node.Text];
                    break;
                //Show all Month of a Year in a Income class
                case 2:
                    _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income, e.Node.Parent.Text, e.Node.Text];
                    break;
                //Show all entries in a Month of a Year in a Income class
                case 3:
                    _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income, e.Node.Parent.Parent.Text, e.Node.Parent.Text, e.Node.Text];
                    dataGridViewIncome.ReadOnly = false;
                    panelInAdd.Enabled = true;
                    break;
            }            
            setUpColumnText(dataGridViewIncome, e.Node.Level + 1);
            setupColorOfDataGrdiView(dataGridViewIncome);
        }
        #endregion

        #endregion
                
        #region EventHandler Outcome


        #region NavigationBar
        private void ultraNavigationBarOutcome_InitializeLocations(object sender, InitializeLocationsEventArgs e)
        {
            dataGridViewOutcome.ReadOnly = true;
            panelOutAdd.Enabled = false;
            String[] path = e.ParentLocation.GetFullPath(FullPathFormat.EditMode).Split(splitChar, StringSplitOptions.None);
            switch (path.Length)
            {
                //Show all Outcome clases in the List
                case 1:
                    foreach (KeyValuePaar<IMoneyFlowItem, Double> item in _moneyFlowDB[EFlowDirection.Outcome])
                    {
                        e.ParentLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome];
                    break;
                //Show all Years in a Outcome class
                case 2:
                    foreach (KeyValuePaar<Year, Double> item in _moneyFlowDB[EFlowDirection.Outcome, e.ParentLocation.DisplayTextResolved])
                    {
                        e.ParentLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.ParentLocation.DisplayTextResolved];
                    break;
                //Show all Month of a Year in a Outcome class
                case 3:
                    foreach (KeyValuePaar<Month, Double> item in _moneyFlowDB[EFlowDirection.Outcome, e.ParentLocation.Parent.Key, e.ParentLocation.DisplayTextResolved])
                    {
                        e.ParentLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.ParentLocation.Parent.Key, e.ParentLocation.DisplayTextResolved];
                    break;
                //Show all entries in aMonth of a Year in a Outcome class
                case 4:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.ParentLocation.Parent.Parent.Key, e.ParentLocation.Parent.Key, e.ParentLocation.DisplayTextResolved];
                    dataGridViewOutcome.ReadOnly = false;
                    panelOutAdd.Enabled = true;
                    break;
            }
            setUpColumnText(dataGridViewOutcome, path.Length);
        }


        private void ultraNavigationBarOutcome_SelectedLocationChanged(object sender, SelectedLocationChangedEventArgs e)
        {
            dataGridViewOutcome.ReadOnly = true;
            panelOutAdd.Enabled = false;
            String[] path = e.SelectedLocation.GetFullPath(FullPathFormat.EditMode).Split(splitChar, StringSplitOptions.None);
            switch (path.Length)
            {
                //Show all Outcome clases in the List
                case 1:
                    e.SelectedLocation.Locations.Clear();
                    foreach (KeyValuePaar<IMoneyFlowItem, Double> item in _moneyFlowDB[EFlowDirection.Outcome])
                    {
                        e.SelectedLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome];
                    break;


                //Show all Years in a Outcome class
                case 2:
                    e.SelectedLocation.Locations.Clear();
                    foreach (KeyValuePaar<Year, Double> item in _moneyFlowDB[EFlowDirection.Outcome, e.SelectedLocation.DisplayTextResolved])
                    {
                        e.SelectedLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.SelectedLocation.DisplayTextResolved];
                    selectNodeinTree(e.SelectedLocation.DisplayTextResolved, EFlowDirection.Outcome);
                    break;


                //Show all Month of a Year in a Outcome class
                case 3:
                    e.SelectedLocation.Locations.Clear();
                    foreach (KeyValuePaar<Month, Double> item in _moneyFlowDB[EFlowDirection.Outcome, e.SelectedLocation.Parent.Key, e.SelectedLocation.DisplayTextResolved])
                    {
                        e.SelectedLocation.Locations.Add(item.Key.ToString(), item.Key.ToString());
                    }
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.SelectedLocation.Parent.Key, e.SelectedLocation.DisplayTextResolved];
                    selectNodeinTree(e.SelectedLocation.Parent.Key + "-" + e.SelectedLocation.DisplayTextResolved, EFlowDirection.Outcome);
                    break;


                //Show all entries in aMonth of a Year in a Outcome class
                case 4:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.SelectedLocation.Parent.Parent.Key, e.SelectedLocation.Parent.Key, e.SelectedLocation.DisplayTextResolved];
                    dataGridViewOutcome.ReadOnly = false;
                    panelOutAdd.Enabled = true;
                    selectNodeinTree(e.SelectedLocation.Parent.Parent.Key + "-" + e.SelectedLocation.Parent.Key + "-" + e.SelectedLocation.DisplayTextResolved, EFlowDirection.Outcome);
                    setUpOutcomeAddComponents();
                    break;
            }
            setUpColumnText(dataGridViewOutcome, path.Length);
        }
        #endregion


        #region Misc
        private void setUpOutcomeAddComponents()
        {
            String[] path = treeViewOutcome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
            listBoxOut.SelectedIndex = listBoxOut.Items.IndexOf(path[1]);
            numericUpDownOutYear.Value = Decimal.Parse(path[2]);
            domainUpDownOutMonth.Text = path[3];
        }

        #endregion

        #region ContextMenu
        private void deleteToolStripMenuItemOutcome_Click(object sender, EventArgs e)
        {
            String[] path = treeViewOutcome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
            if (!dataGridViewOutcome.Rows[hitTestInfoOut.RowIndex].IsNewRow && path.Length > 3)
            {
                DialogResult response = MessageBox.Show("Are you sure want to delete the row?", "Sample", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                if (response == DialogResult.Yes)
                {
                    dataGridViewOutcome.Rows.RemoveAt(hitTestInfoOut.RowIndex);
                    _moneyFlowDB.Delete(EFlowDirection.Outcome, path[1], path[2], path[3], hitTestInfoOut.RowIndex);
                    _moneyFlowDB.Sum(EFlowDirection.Outcome);
                }
            }
        }
        
        private void refreshToolStripMenuItemOutcome_Click(object sender, EventArgs e)
        {
            _moneyFlowDB.Sum(EFlowDirection.Outcome);
        }

        private void dataGridViewOutcome_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                hitTestInfoOut = dataGridViewOutcome.HitTest(e.X, e.Y);
                if (hitTestInfoOut.RowIndex >= 0 && hitTestInfoOut.ColumnIndex > 0)
                {
                    if (!dataGridViewOutcome.Rows[hitTestInfoOut.RowIndex].IsNewRow)
                    {
                        if (hitTestInfoOut.Type == DataGridViewHitTestType.Cell)
                        {
                            contextMenuStripOut.Show(dataGridViewOutcome, new Point(e.X, e.Y));
                        }
                        dataGridViewOutcome.Rows[hitTestInfoOut.RowIndex].Selected = true;
                        dataGridViewOutcome.CurrentCell = dataGridViewOutcome[hitTestInfoOut.ColumnIndex, hitTestInfoOut.RowIndex];
                    }
                }
            }
        }
#endregion

        #region TreeNode
        private void BuildTreeOutcome()
        {
            treeViewOutcome.Nodes[0].Nodes.Clear();
            //Outcome - Treeview
            foreach (KeyValuePaar<IMoneyFlowItem, Double> classReference in _moneyFlowDB[EFlowDirection.Outcome])
            {
                treeViewOutcome.BeginUpdate();
                String name = classReference.Key.Classname;
                treeViewOutcome.Nodes[0].Nodes.Add(name, name);

                foreach (KeyValuePaar<Year, Double> year in _moneyFlowDB[EFlowDirection.Outcome, name])
                {
                    treeViewOutcome.Nodes[0].Nodes[name].Nodes.Add(name + "-" + year.Key.ToString(), year.Key.ToString());
                    foreach (KeyValuePaar<Month, Double> month in _moneyFlowDB[EFlowDirection.Outcome, name, year.Key.ToString()])
                    {
                        treeViewOutcome.Nodes[0].Nodes[name].Nodes[name + "-" + year.Key.ToString()].Nodes.Add(name + "-" + year.Key.ToString() + "-" + month.Key.ToString(), month.Key.ToString());
                    }
                }
                treeViewOutcome.EndUpdate();
            }
        }


        private void treeViewOutcome_AfterSelect(object sender, TreeViewEventArgs e)
        {
            panelOutAdd.Enabled = false;
            dataGridViewOutcome.ReadOnly = true;
            _historyOutBackStack.Push(new Pfad(e.Node.FullPath));
            switch (e.Node.Level)
            {
                //Show all Outcome clases in the List
                case 0:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome];
                    break;
                //Show all Years in a Outcome class
                case 1:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.Node.Text];
                    break;
                //Show all Month of a Year in a Outcome class
                case 2:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.Node.Parent.Text, e.Node.Text];
                    break;
                //Show all entries in a Month of a Year in a Outcome class
                case 3:
                    _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, e.Node.Parent.Parent.Text, e.Node.Parent.Text, e.Node.Text];
                    dataGridViewOutcome.ReadOnly = false;
                    panelOutAdd.Enabled = true;
                    break;
            }
            setUpColumnText(dataGridViewOutcome, e.Node.Level + 1);
        }
        #endregion



        #endregion        

        #region EventHandler MainForm

        #region Form Load
        
        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            setUpMainForm();
            setupColorOfDataGrdiView(dataGridViewIncome);
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            _moneyFlowDB.checkDateChanged();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                _moneyFlowDB.Serialize(SERIALIZED_FILE_NAME);
            }
            catch (FileNotFoundException err)
            {
                MessageBox.Show("The File "+ err.FileName + " could not be found!");
            }
            catch (SerializationException)
            {
                MessageBox.Show("The File " + SERIALIZED_FILE_NAME+" could not be serialized, this could have several issues.");
            }            
        }
        #endregion

        #region Search
        private void textBoxOutSearch_TextChanged(object sender, EventArgs e)
        {
            if (textBoxOutSearch.Text != "" && !WhiteSpaceRegex.Match(textBoxOutSearch.Text).Success)
            {
                String[] path = treeViewOutcome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
                
                switch (path.Length)
                {
                    //Search all Income classes in the List
                    case 1:
                        _datenBinderOutcome.DataSource = _moneyFlowDB.Find(EFlowDirection.Outcome, textBoxOutSearch.Text);
                        break;

                    //Search all Years in a Income class
                    case 2:
                        _datenBinderOutcome.DataSource = _moneyFlowDB.Find(EFlowDirection.Outcome, path[1], textBoxOutSearch.Text);
                        break;

                    //Search all Month of a Year in a Income class
                    case 3:
                        _datenBinderOutcome.DataSource = _moneyFlowDB.Find(EFlowDirection.Outcome, path[1], path[2], textBoxOutSearch.Text);
                        break;

                    //Search all entries in a Month of a Year in a Income class
                    case 4:
                        _datenBinderOutcome.DataSource = _moneyFlowDB.Find(EFlowDirection.Outcome, path[1], path[2], path[3], textBoxOutSearch.Text);
                        break;
                }
                dataGridViewOutcome.ReadOnly = false;
            }
            else
            {
                //navigationBarOutcome.NavigateTo(treeViewIncome.SelectedNode.FullPath, true);
            }
        }

        private void textBoxInSearch_TextChanged(object sender, EventArgs e)
        {
            if (textBoxInSearch.Text != "" && !WhiteSpaceRegex.Match(textBoxInSearch.Text).Success)
            {
                //textBoxInSearch.Text = dataGridViewOutcome.DataBindings.BindableComponent.DataBindings.GetType().FullName.ToString();
                String[] path = treeViewIncome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
                switch (path.Length)
                {
                    //Search all Income classes in the List
                    case 1:
                        _datenBinderIncome.DataSource = _moneyFlowDB.Find(EFlowDirection.Income, textBoxInSearch.Text);
                        break;


                    //Search all Years in a Income class
                    case 2:
                        _datenBinderIncome.DataSource = _moneyFlowDB.Find(EFlowDirection.Income, path[1], textBoxInSearch.Text);
                        break;


                    //Search all Month of a Year in a Income class
                    case 3:


                        _datenBinderIncome.DataSource = _moneyFlowDB.Find(EFlowDirection.Income, path[1], path[2], textBoxInSearch.Text);
                        break;


                    //Search all entries in a Month of a Year in a Income class
                    case 4:
                        _datenBinderIncome.DataSource = _moneyFlowDB.Find(EFlowDirection.Income, path[1], path[2], path[3], textBoxInSearch.Text);
                        break;
                }
                dataGridViewIncome.ReadOnly = false;
            }
            else
            {
                //navigationBarIncome.NavigateTo(treeViewIncome.SelectedNode.FullPath, true);
            }
        }
        #endregion

        #region Add


        private void buttonInClear_Click(object sender, EventArgs e)
        {
            textBoxInAddComment.Text = "";
            textBoxInAddValue.Text = "";
            listBoxIn.ClearSelected();

            domainUpDownInMonth.SelectedIndex = _moneyFlowDB.CurrentMonth - 1;
            numericUpDownInYear.Value = _moneyFlowDB.CurrentYear;

            textBoxInAddComment.Focus();
        }


        private void buttonOutClear_Click(object sender, EventArgs e)
        {


            textBoxOutAddComment.Text = "";
            textBoxOutAddValue.Text = "";
            listBoxOut.ClearSelected();
            domainUpDownOutMonth.SelectedIndex = _moneyFlowDB.CurrentMonth - 1;
            numericUpDownOutYear.Value = _moneyFlowDB.CurrentYear;
        }


        private void buttonInAdd_Click(object sender, EventArgs e)
        {
            bool successDigit = DigitRegex.Match(textBoxInAddValue.Text).Success;
            bool successWS = WhiteSpaceRegex.Match(textBoxInAddComment.Text).Success;
            bool successYear = (YearRegex.Match(numericUpDownInYear.Value.ToString()).Success && numericUpDownInYear.Value.ToString().Length == 4);
            bool successIn = listBoxIn.Text != "";
            bool successMonth = MonthInEnum(domainUpDownInMonth.Text);


            if (successDigit && textBoxInAddComment.Text != "" && !successWS && successYear && successIn && successMonth)
            {
                _moneyFlowDB.Add(EFlowDirection.Income, listBoxIn.Text, numericUpDownInYear.Value.ToString(), domainUpDownInMonth.Text, textBoxInAddComment.Text, Double.Parse(textBoxInAddValue.Text));
                _moneyFlowDB.Sum(EFlowDirection.Income);
                _datenBinderIncome.DataSource = null;
                _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income, listBoxIn.Text, numericUpDownInYear.Value.ToString(), domainUpDownInMonth.Text];
                textBoxInAddValue.Text = "";
                textBoxInAddComment.Text = "";
                textBoxInAddComment.Focus();
            }
        }


        private void buttonOutAdd_Click(object sender, EventArgs e)
        {
            bool successDigit = DigitRegex.Match(textBoxOutAddValue.Text).Success;
            bool successWS = WhiteSpaceRegex.Match(textBoxOutAddComment.Text).Success;
            bool successYear = (YearRegex.Match(numericUpDownOutYear.Value.ToString()).Success && numericUpDownInYear.Value.ToString().Length == 4);
            bool successOut = listBoxOut.Text != "";
            bool successMonth = MonthInEnum(domainUpDownOutMonth.Text);


            if (successDigit && textBoxOutAddComment.Text != "" && !successWS && successYear && successOut && successMonth)
            {
                _moneyFlowDB.Add(EFlowDirection.Outcome, listBoxOut.Text, numericUpDownOutYear.Text, domainUpDownOutMonth.Text, textBoxOutAddComment.Text, Convert.ToDouble(textBoxOutAddValue.Text));
                _moneyFlowDB.Sum(EFlowDirection.Outcome);
                _datenBinderOutcome.DataSource = null;
                _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome, listBoxOut.Text, numericUpDownOutYear.Text, domainUpDownOutMonth.Text];
                textBoxOutAddValue.Text = "";
                textBoxOutAddComment.Text = "";
                textBoxOutAddValue.Focus();
            }
        }


        private void textBoxAddValue_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!DigitRegex.Match(((TextBox)sender).Text).Success)
            {
                ((TextBox)sender).ForeColor = Color.Red;
            }
            else
            {
                ((TextBox)sender).ForeColor = Color.Black;
            }
        }

                
       
        private void domainUpDownMonth_TextChanged(object sender, EventArgs e)
        {
            Boolean included = MonthInEnum(((DomainUpDown)sender).Text);
            if (included)
            {
                ((DomainUpDown)sender).ForeColor = Color.Black;
            }
            else
            {
                ((DomainUpDown)sender).ForeColor = Color.Red;
            }
        }

       


        #endregion

        #region Navigation

        private void navigateUp(EFlowDirection flowdir, TreeView treeview, Stack<Pfad> backStack)
        {
            Pfad pfad = new Pfad(treeview.SelectedNode.FullPath);
            backStack.Push(pfad);

            if (pfad.Count > 2)
            {
                selectNodeinTree(pfad.pathWithHyphen(true, true), flowdir);
            }
            else
            {
                treeview.SelectedNode = treeview.Nodes[0];
            }
        }

        private void navigateBack(EFlowDirection flowdir, TreeView treeview, Stack<Pfad> backStack, Stack<Pfad> forwardStack)
        {
            if (backStack.Count > 0)
            {
                Pfad newPath = backStack.Pop();
                forwardStack.Push(newPath);
                if (newPath.Count > 2)
                {
                    selectNodeinTree(newPath.pathWithHyphen(true, false), flowdir);
                }
                else
                {
                    treeview.SelectedNode = treeview.Nodes[0];
                }
            }
        }

        private void navigateForward(EFlowDirection flowdir, TreeView treeview, Stack<Pfad> backStack, Stack<Pfad> forwardStack)
        {
            if (forwardStack.Count > 0)
            {
                Pfad newPath = forwardStack.Pop();
                backStack.Push(newPath);
                if (newPath.Count > 2)
                {
                    selectNodeinTree(newPath.pathWithHyphen(true, false), flowdir);
                }
                else
                {
                    treeview.SelectedNode = treeview.Nodes[0];
                }
            }
        }


        private void buttonInUp_Click(object sender, EventArgs e)
        {
            navigateUp(EFlowDirection.Income, treeViewIncome, _historyInBackStack);
        }

        private void buttonInBack_Click(object sender, EventArgs e)
        {
            navigateBack(EFlowDirection.Income, treeViewIncome, _historyInBackStack, _historyInForwardStack);
        }
        
        private void buttonInForward_Click(object sender, EventArgs e)
        {
            navigateForward(EFlowDirection.Income, treeViewIncome, _historyInBackStack, _historyInForwardStack);
        }


        private void buttonOutUp_Click(object sender, EventArgs e)
        {
            navigateUp(EFlowDirection.Outcome, treeViewOutcome, _historyOutBackStack);
        }

        private void buttonOutBack_Click(object sender, EventArgs e)
        {
            navigateBack(EFlowDirection.Outcome, treeViewOutcome, _historyOutBackStack, _historyOutForwardStack);
        }

        private void buttonOutForward_Click(object sender, EventArgs e)
        {
            navigateForward(EFlowDirection.Outcome, treeViewOutcome, _historyOutBackStack, _historyOutForwardStack);
        }


        #endregion

        #region Menu

        #region Datei
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult response = MessageBox.Show("Wollen Sie wirklich eine neue Datenbank anlegen?", "Neue Datenbank anlegen", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (response == DialogResult.Yes)
            {
                _moneyFlowDB = new MoneyFlowTreeHandler(TABLE_NAME_LEFT, TABLE_NAME_RIGHT);
                _moneyFlowDB.CurrentFilename = SERIALIZED_FILE_NAME;
                switch (MFSetup.ShowDialog())
                {
                    case DialogResult.Cancel:
                        break;
                    case DialogResult.OK:
                        _moneyFlowDB.initController(MFSetup.ItemList, false);
                        break;
                    default:
                        break;
                }
            }
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool userNotCancel = true;
            if (_moneyFlowDB.Dirty)
            {
                DialogResult response = MessageBox.Show("You have unsaved data! Save now?", "Save", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (response == DialogResult.Yes)
                {
                    try
                    {
                        _moneyFlowDB.Serialize(_moneyFlowDB.CurrentFilename);
                    }
                    catch (FileNotFoundException err)
                    {
                        MessageBox.Show("The File " + err.FileName + " could not be found!");
                    }
                    catch (SerializationException)
                    {
                        MessageBox.Show("The File " + _moneyFlowDB.CurrentFilename + " could not be serialized, this could have several issues.");
                    }
                }
                if (response == DialogResult.Cancel)
                {
                    userNotCancel = false;
                }
            }
            else if (userNotCancel)
            {
                OpenFileDialog fd = new OpenFileDialog();
                fd.Title = "Choose a Database";
                fd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                fd.Filter = "Database (*.ogo)|*.ogo|" + "Xml (*xml)| *.xml";
                fd.CheckFileExists = true;

                if (fd.ShowDialog() == DialogResult.OK)
                {
                    if (fd.FileName.Split('.')[1].Equals("ogo"))
                    {
                        try
                        {
                            _moneyFlowDB.openDatabase(fd.FileName);
                            setUpMainForm();
                            _datenBinderIncome.DataSource = _moneyFlowDB[EFlowDirection.Income];
                            _datenBinderOutcome.DataSource = _moneyFlowDB[EFlowDirection.Outcome];
                        }
                        catch (Exception err)
                        {
                            MessageBox.Show("Die Datei: " + fd.FileName + " konnte nicht gefunden werden \n Error Message: \t" + err.Message);
                        }
                    }
                    else if (fd.FileName.Split('.')[1].Equals("xml"))
                    {

                    }
                } 
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                _moneyFlowDB.Serialize(_moneyFlowDB.CurrentFilename);
            }
            catch (FileNotFoundException err)
            {
                MessageBox.Show("The File " + err.FileName + " could not be found!");
            }
            catch (SerializationException)
            {
                MessageBox.Show("The File " + SERIALIZED_FILE_NAME + " could not be serialized, this could have several issues.");
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "ogo";
            sfd.Filter = "Ogo | *.ogo";


            if (sfd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    _moneyFlowDB.Serialize(sfd.FileName);
                }
                catch (FileNotFoundException)
                {
                    MessageBox.Show("The File " + sfd.FileName + " could not be found!");
                }
                catch (SerializationException)
                {
                    MessageBox.Show("The File " + sfd.FileName + " could not be serialized, this could have several issues.");
                }
            }
        }

        private void xmlToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _moneyFlowDB.Sum(EFlowDirection.Income);
            _moneyFlowDB.Sum(EFlowDirection.Outcome);


            XmlDocument moneyFlowDBXml = new XmlDocument();

            XmlElement rootElem = moneyFlowDBXml.CreateElement("MoneyFlowDB");
            moneyFlowDBXml.AppendChild(rootElem);


            foreach (IMoneyFlowController controller in _moneyFlowDB)
            {
                XmlElement flowdirElem = moneyFlowDBXml.CreateElement(controller.ToString());
                rootElem.AppendChild(flowdirElem);


                foreach (KeyValuePaar<IMoneyFlowItem, Double> item in controller)
                {
                    XmlElement moneyflowitem = moneyFlowDBXml.CreateElement(item.Key.ToString());
                    XmlAttribute sumAttrItem = moneyFlowDBXml.CreateAttribute("Sum");
                    sumAttrItem.Value = item.Value.ToString();
                    moneyflowitem.Attributes.Append(sumAttrItem);
                    flowdirElem.AppendChild(moneyflowitem);


                    foreach (KeyValuePaar<Year, Double> year in item.Key)
                    {
                        XmlElement yearitem = moneyFlowDBXml.CreateElement("Jahr-" + year.Key.ToString());
                        XmlAttribute sumAttrYear = moneyFlowDBXml.CreateAttribute("Sum");
                        sumAttrYear.Value = year.Value.ToString();
                        yearitem.Attributes.Append(sumAttrYear);
                        moneyflowitem.AppendChild(yearitem);


                        foreach (KeyValuePaar<Month, Double> month in year.Key)
                        {
                            XmlElement monthitem = moneyFlowDBXml.CreateElement(month.Key.ToString());
                            XmlAttribute sumAttrMonth = moneyFlowDBXml.CreateAttribute("Sum");
                            sumAttrMonth.Value = month.Value.ToString();
                            monthitem.Attributes.Append(sumAttrMonth);
                            yearitem.AppendChild(monthitem);

                            foreach (KeyValuePaar<String, Double> entity in month.Key)
                            {
                                XmlElement entityitem = moneyFlowDBXml.CreateElement("Entry");
                                entityitem.InnerText = entity.Key;
                                XmlAttribute sumAttrEntity = moneyFlowDBXml.CreateAttribute("Sum");
                                sumAttrEntity.Value = entity.Value.ToString();
                                entityitem.Attributes.Append(sumAttrEntity);
                                monthitem.AppendChild(entityitem);
                            }
                        }
                    }
                }
            }
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "xml";
            sfd.Filter = "Xml | *.xml";


            if (sfd.ShowDialog() == DialogResult.OK)
            {
                String strFile = sfd.FileName;
                XmlTextWriter textWriter = new XmlTextWriter(strFile, System.Text.Encoding.Unicode);
                textWriter.WriteStartDocument();
                moneyFlowDBXml.Save(textWriter);
                textWriter.WriteEndDocument();
                textWriter.Close();
            }


        }

        private String getColumnNamebyindex(int index)
        {
            int alphabetCount = 26;
            int charValueA = 65;
            //int charValueZ = 90;
            Double charOffset = ((Double)index) / alphabetCount;

            if (charOffset <= 1)
            {
                return ((char)(charValueA + index - 1)).ToString();
            }
            else
            {
                char firstChar = (char)(charValueA + ((int)charOffset) - 1);
                char seccondChar = (char)(index - ((int)charOffset) * alphabetCount + charValueA - 1);
                return (firstChar).ToString() + (seccondChar).ToString();
            }
        }

        private void excelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ExcelFile xlsFile = new ExcelFile();
            xlsFile.DefaultFontSize = 11;
            xlsFile.Worksheets.Add("MoneyFlow");


            int zeilenZaehler = 1;
            int spaltenZaehler = 1;
            int outSpaltenOffset = _moneyFlowDB[EFlowDirection.Income].Count + 2;


            IMoneyFlowController incontroller = _moneyFlowDB[EFlowDirection.Income];
            IMoneyFlowController outcontroller = _moneyFlowDB[EFlowDirection.Outcome];


            int yearCount = incontroller[incontroller.Count - 1].Key.Database.Count;
            int monthCount = incontroller[incontroller.Count - 1].Key.Database[yearCount - 1].Key.Count;


            _moneyFlowDB.Sum(EFlowDirection.Income);
            _moneyFlowDB.Sum(EFlowDirection.Outcome);




            xlsFile.Worksheets["MoneyFlow"].Cells["B1"].Value = "Income";
            xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler + outSpaltenOffset + 1) + "1"].Value = "Outcome";
            zeilenZaehler++;

            //Jahre
            for (int i = 0; i < yearCount; i++)
            {
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler + i * (monthCount + 1)).ToString()].Value = incontroller[incontroller.Count - 1].Key.Database[i].Key.ToString();
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler + outSpaltenOffset) + (zeilenZaehler + i * (monthCount + 1)).ToString()].Value = incontroller[incontroller.Count - 1].Key.Database[i].Key.ToString();
            }
            //Summe von Income bzw Outcome
            spaltenZaehler++;
            xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + zeilenZaehler.ToString()].Value = incontroller.SumValue;
            xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler + outSpaltenOffset) + zeilenZaehler.ToString()].Value = outcontroller.SumValue;
            zeilenZaehler++;


            //Monate
            for (int i = 0; i < monthCount; i++)
            {
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler + i).ToString()].Value = incontroller[incontroller.Count - 1].Key.Database[yearCount - 1].Key[i].Key.ToString();
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler + outSpaltenOffset) + (zeilenZaehler + i).ToString()].Value = incontroller[incontroller.Count - 1].Key.Database[yearCount - 1].Key[i].Key.ToString();
            }
            zeilenZaehler = 1;
            spaltenZaehler = 3;
            //Elemente ind Income bzw. Outcome
            foreach (KeyValuePaar<IMoneyFlowItem, Double> item in incontroller)
            {
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Key.Classname;
                zeilenZaehler++;
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Value;
                for (int i = 0; i < yearCount; i++)
                {
                    for (int j = 0; j < monthCount; j++)
                    {
                        xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Key.Database[i].Key[j].Key.SumOfMonth;
                        zeilenZaehler++;
                    }
                }
                zeilenZaehler = 1;
                spaltenZaehler++;
            }

            zeilenZaehler = 1;
            spaltenZaehler = 3 + outSpaltenOffset;
            foreach (KeyValuePaar<IMoneyFlowItem, Double> item in outcontroller)
            {
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Key.Classname;
                zeilenZaehler++;
                xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Value;
                for (int i = 0; i < yearCount; i++)
                {
                    for (int j = 0; j < monthCount; j++)
                    {
                        xlsFile.Worksheets["MoneyFlow"].Cells[getColumnNamebyindex(spaltenZaehler) + (zeilenZaehler).ToString()].Value = item.Key.Database[i].Key[j].Key.SumOfMonth;
                        zeilenZaehler++;
                    }
                }
                zeilenZaehler = 1;
                spaltenZaehler++;
            }




            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.DefaultExt = "xls";
            sfd.Filter = "Xls | *.xls";


            if (sfd.ShowDialog() == DialogResult.OK)
            {
                String strFile = sfd.FileName;
                xlsFile.SaveXls(strFile);
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_moneyFlowDB.Dirty)
            {
                DialogResult response = MessageBox.Show("You have unsaved data! Save now?", "Save", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (response == DialogResult.Yes)
                {
                    try
                    {
                        _moneyFlowDB.Serialize(_moneyFlowDB.CurrentFilename);
                    }
                    catch (FileNotFoundException err)
                    {
                        MessageBox.Show("The File " + err.FileName + " could not be found!");
                    }
                    catch (SerializationException)
                    {
                        MessageBox.Show("The File " + SERIALIZED_FILE_NAME + " could not be serialized, this could have several issues.");
                    }
                }
            }
            this.Close();
        } 
        #endregion


        private void customizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            switch (MFSetup.ShowDialog())
            {
                case DialogResult.Cancel:
                    break;
                case DialogResult.OK:
                    _moneyFlowDB.initController(MFSetup.ItemList, true);
                    setUpMainForm();
                    break;
                default:
                    break;
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("FinanceAnalyzer by ogino \ncopyright 2009", "About", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }


        #endregion

        private void dataGridViewIncome_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            String[] path = treeViewIncome.SelectedNode.FullPath.Split(splitChar, StringSplitOptions.None);
            if (path.Length > 3)
            {
                IMoneyFlowController controller = _moneyFlowDB[EFlowDirection.Income];
                Year betroffenesJahr = controller[path[1], path[2]];
                       
                //_moneyFlowDB.registerUndoState(EFlowDirection.Income, path, betroffenesJahr[betroffenesJahr.IndexOf(path[3])].Key);
            }
        }

        private void buttonInUndo_Click(object sender, EventArgs e)
        {
            //_moneyFlowDB.undo(EFlowDirection.Income);
            dataGridViewIncome.Invalidate();
        }

        private void buttonInRedo_Click(object sender, EventArgs e)
        {
            //_moneyFlowDB.redo(EFlowDirection.Income);
        }


        #endregion

        
    }
}